package cn.mw.cmdb.entity;

import cn.mw.cmdb.param.ImportContextParam;
import cn.mw.components.mongodb.entity.CriteriaOpsType;
import cn.mw.microMonitorCommon.api.user.MwUserApi;
import cn.mw.microMonitorCommon.entity.cmdb.ModelExportDataInfoParam;
import cn.mw.microMonitorCommon.entity.cmdb.MwImportResultParam;
import cn.mw.microMonitorCommon.security.dto.MwUser;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.nacos.shaded.com.google.common.base.Strings;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.context.ApplicationContext;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.util.*;
import java.util.stream.Collectors;

import static cn.mw.cmdb.entity.PropertyTypeNumerical.isNumeric;
import static cn.mw.cmdb.service.impl.InstanceViewImpl.*;

@Service
public class PropertyTypeUser extends PropertyType<PropertyTypeUser, Object> {
    public static final String ID = "users";
    private static List<MwUser> finalList = new ArrayList<>();
    private static List<String> finalNickNameList = new ArrayList<>();
    private static ApplicationContext applicationContext;
    @DubboReference(check = false, mock = "true",timeout = 15000)
    public MwUserApi mwUserApi;

    public PropertyTypeUser() {
        setId(ID);
        setName("负责人");
        setSortNum(12);
    }

    @Override
    public Object convertValue(Object value) {
        if (value == null) {
            return null;
        }
        if (!isNumeric(value) && !(value instanceof List)) {
            MwUserApi userApi = PropertyType.userApi;
            List<Long> userIdList = new ArrayList<>();
            List<MwUser> usersByUsernames = new ArrayList<>();
            List<String> list = Arrays.asList(strValueConvert(value).split(","));
            if (!CollectionUtils.isEmpty(list)) {
                usersByUsernames = userApi.getUsersByNicknames(new ArrayList<>(list));
            }
            setUserIds(usersByUsernames, value, userIdList);
            return userIdList;
        } else {
            return value;
        }
    }

    @Override
    public Object tableHeaderTipInfo(PropertyTypeRef propertyTypeRef) {
        return "多个数据用“,”隔开";
    }

    @Override
    public Criteria doCriteria(CriteriaOpsType opsType, String name, Object value) {
        MwUserApi userApi = PropertyType.userApi;
        List<Long> userIds = new ArrayList<>();
        if (userApi != null && !isNumeric(value) && !(value instanceof List)) {
            List<MwUser> usersByNicknames = userApi.getUsersByNicknames(Arrays.asList(strValueConvert(value)));
            if (!CollectionUtils.isEmpty(usersByNicknames)) {
                for (MwUser mwUser : usersByNicknames) {
                    userIds.add(mwUser.getId());
                }
            }
            value = userIds;
        }
        Criteria criteria = null;
        switch (opsType) {
            case is:
            case like:
            case in:
                if (value instanceof List) {
                    criteria = new Criteria(name).in(((List<?>) value).toArray());
                } else {
                    criteria = new Criteria(name).in(value);
                }
                break;
            case nin:
                if (value instanceof List) {
                    criteria = new Criteria(name).nin(((List<?>) value).toArray());
                } else {
                    criteria = new Criteria(name).nin(value);
                }
                break;
            case elemMatch:
                criteria = new Criteria(name).elemMatch(new Criteria().in(JSONArray.parse(strValueConvert(value))));
                break;
            case exist:
                criteria = new Criteria(name).exists((boolean) value);
                break;
            case ne:
                criteria = new Criteria(name).ne(value);
        }
        return criteria;
    }

    @Override
    public CriteriaOpsType getDefaultCriteriaOpsType() {
        return CriteriaOpsType.in;
    }

    @Override
    public PropertyTypeUser newObj() {
        return new PropertyTypeUser();
    }

    @Override
    public void refresh() {
        finalList.clear();
        finalNickNameList.clear();
    }

    @Override
    public boolean tableHeaderInfo(Map ms, PropertyInfo propertyInfo, List<String> labelNames, List<String> labelId) throws Exception {
        //导出表头数据时，表头字段的id和名称不能同时重复
        if ((labelId != null && !labelId.contains(propertyInfo.getId())) && (labelNames != null && !labelNames.contains(ms.get(nameKey)))) {
            ms.put(typeKey, PropertyTypeUser.ID);
            List<String> nickNameList = new ArrayList<>();
            MwUserApi mwUserApi = PropertyType.userApi;
            List<MwUser> usersByUsernames = new ArrayList<>();
            if (CollectionUtils.isEmpty(finalNickNameList)) {
                //调用公共接口，获取对应的信息
                usersByUsernames = mwUserApi.getUsersByNicknames(new ArrayList<>());
                if (!CollectionUtils.isEmpty(usersByUsernames)) {
                    for (MwUser mwUser : usersByUsernames) {
                        String nickName = mwUser.getNickName();
                        nickNameList.add(nickName);
                    }
                    if (!CollectionUtils.isEmpty(nickNameList)) {
                        finalNickNameList = nickNameList;
                    }
                }
            } else {
                nickNameList = finalNickNameList;
            }
            labelId.add(propertyInfo.getId());
            ms.put(selectDataKey, nickNameList);
            return true;
        }
        return false;
    }

    @Override
    public Object getDataValue(ImportContextParam contextParam) {
        MwImportResultParam resultParam = new MwImportResultParam();
        List<Long> userIdList = new ArrayList<>();
        String message = "";
        List<ModelExportDataInfoParam> list = contextParam.getListInfos();
        if (CollectionUtils.isEmpty(list)) {
            resultParam.setMessage("获取解析失败");
            return resultParam;
        }
        Set<String> nickNames = list.stream().filter(s -> !Strings.isNullOrEmpty(strValueConvert(s.getCellValue())) && ID.equals(s.getPropertyType())).map(s -> strValueConvert(s.getCellValue())).collect(Collectors.toSet());
        Set<String> disNickNames = new HashSet<>();
        if (!CollectionUtils.isEmpty(nickNames)) {
            for (String nickName : nickNames) {
                String[] userArr = strValueConvert(nickName).split(",");
                for (String userStr : userArr) {
                    disNickNames.add(userStr);
                }
            }
        }


        ModelExportDataInfoParam importParam = contextParam.getParam();
        //属性名称
        String tableName = importParam.getTableName();
        Object cellValue = importParam.getCellValue();
        Map<String, Object> matchMap = new HashMap<>();
        importCheckInfo(resultParam, contextParam, matchMap);
        MwUserApi mwUserApi = contextParam.getMwUserApi();
        if (Strings.isNullOrEmpty(strValueConvert(cellValue))) {
            return resultParam;
        }
        List<MwUser> usersByUsernames = new ArrayList<>();
        if (CollectionUtils.isEmpty(finalList)) {
            //调用公共接口，获取对应的信息
            if (!CollectionUtils.isEmpty(disNickNames)) {
                usersByUsernames = mwUserApi.getUsersByNicknames(new ArrayList<>(disNickNames));
            }
            finalList = new ArrayList<>(usersByUsernames);
        }
        usersByUsernames = finalList;
        message = setUserIds(usersByUsernames, cellValue, userIdList);
        resultParam.setMessage(message);
        resultParam.setCellValue(userIdList);
        return resultParam;
    }

    public String setUserIds(List<MwUser> usersByUsernames, Object value, List<Long> userIdList) {
        String message = "";
        Map<String, Long> nameByIdMap = usersByUsernames.stream().collect(Collectors.toMap(s -> s.getNickName(), s -> s.getId(), (
                value1, value2) -> {
            return value2;
        }));
        String[] userArr = strValueConvert(value).split(",");
        if (userArr != null) {
            for (String userName : userArr) {
                if (nameByIdMap != null && nameByIdMap.containsKey(userName)) {
                    Long userId = nameByIdMap.get(userName);
                    userIdList.add(userId);
                } else {
                    message += userName + "不存在";
                }
            }
        }
        return message;
    }
}
